【レポート】Unity+AWSによるマネージドなゲームサーバ運用 #Amazon Game Developers Conference #AmazonGameTech #AmznGameTechJP
はじめに
こんにちは、AWS事業本部の島川です。
本記事は11月20日、Amazon Game Developers Conferenceで行われた「Unity+AWSによるマネージドなゲームサーバ運用」のセッションレポートです!
セッション概要
一般的なリレー通信によるマルチプレイの実装は、敷居が低い一方でチート耐性の低さや大人数に対応できないなどの問題があります。 弊社ではより本格的なマルチプレイゲーム開発のためのゲームサーバをUnityで実装し、チート耐性と大人数、大規模なゲームプレイを両立する取り組みを行っており、その実装例および、GameLiftやLambdaといったAWSの強力かつマネージドなソリューションによって運用するお話をさせて頂きたいと思います。
スピーカー
株式会社ミクシィ ゲームエンジニア 小端 みより 氏
内容
以前Unityでゲームサーバを実装して運用する内容の講演をUnite Tokyo2019でされていて、こちらのお話がもとになっています。合わせてご覧いただくと面白いと思います!
Unityサーバを作るまで
これまで
- リレーサーバを用いたマルチプレイ実装が主流
- P2Pがたの通信モデルなのでサーバは原則的にロジックに関与しない
- クライアント処理型
メリット
リレーサーバを用いた - ミドルウェアやサービスが豊富クラウド型のサービスならサーバ不要であり手軽 - クライアントで完結するのでプロトタイピングに最適
デメリット
- クライアント処理なのでチートされやすい、不安定になりやすい(ホストマイグレーションなど)
- 実装が複雑化しやすい傾向にあり大人数、大規模なタイトルの開発は難しい。
- 決して万能ではない
それなら
- チート体制、安定性を備え持つ
- リアルタイムで大人数、
- サーバ実装型にすればいい。
ただし
- サーバを実装するのは言語が違う、わからない、手軽さに及ばないといったハードルの高さがある。
- 気軽に開発出来たら嬉しい...。→Unityサーバがある。
Unityサーバとは
- C#で開発できる
- Unityの機能、AnimationやPhysicsやAIを活用できる
- サーバとクライアントを同時に単一プロジェクトで開発できる
やってみた
- アクション性の高いオンラインマルチプレイのゲーム
- サーバとクライアントを単一Unityプロジェクトで作成
- (サーバはLinux,クライアントはiOS/Android)
- サーバをクラウド上で動作させて同時に20人以上プレイ
設計
- サーバ集中処理型の通信モデルを採用
- 上り/下りともに非同期的に最大で毎秒30回の処理を行う
- ゲームは60FPSで動作
- DOTSではなく使い慣れたコンポー年トモデルを採用
- サーバ・クライアント上でコード及びアセットを共有し、Editor上に任意にサーバーやクライアントを実行
サーバー集中処理型とは
- クライアントA、Bともにゲームサーバに送る。
- ゲームサーバーでアップデート、クライアントに送信
- クライアントは受け取る
- かなりシンプルに実装できる
ただし
- サーバ集中処理型は設計をシンプルにできる一方でネットワーク遅延の影響が大きそう。
- アクションゲームとかでは特に課題になるのではないか。
AWSがあった
- ネットワーク遅延の影響が大きくなるため
- 安定した高品質なインフラ環境が必要
- 運用コストが高騰するのではないか
- GameLiftがある!!
Amazon GameLiftについて
- ゲームサーバ運用に特化されたマネージドサービス
- サーバをデプロイするだけでプロセスの起動や監視、スケーリングなどもすべてやってくれる
- AWSのインフラを使用するため低レイテンシかつ高信頼な通信環境を実現できる
- 運用コストも使い方次第で抑えられる
- 2種類ある。
リアルタイムサーバ(新機能)
- JavaScriptによる簡易的な実装
カスタムゲームサーバ
- 従来型のゲームサーバで、本格的なゲーム開発に適する
- 今回はこちらの話
導入手順
GameLift Server SDKの導入
- SDKに含まれるC#版SDKをビルドし、出力されたDLL群をUnityプロジェクトにインポート
- SDKのつなぎこみを行う
- 自前のサーバーのコードから、GameLift ServerAPIの呼び出しやコールバック処理への対応を行う。
- 具体的には、サーバ起動時にSDKの初期化やプロセス軌道の通知、セッション開始やヘルスチェックのコールバック処理など
- SDKドキュメント参照(GameLift)
コールバック実装の注意点
- APIのコールバックは別スレッドから行われる
- ただし、Unityライブラリは基本的にUnityメインスレッドでのみ呼び出される前提で設計されている。
- ↑を避けるためにUnity SynchronizationContextを使う
- Unityメインスレッド内から下記のようにUnitySynchronizationContextを保存しておく
mSyncContext = SynchronizationContext.Current;
- 他スレッドから呼び出されるコールバック関数について
mSyncContext.Post(MyCallback,params);
のようにすれば"MyCallback"がUnityメインスレッド内で実行される
サーバのビルド
- Unityでサーバをビルドする際、GameLiftそのものはWindowsおよびLinuxをサポートしているのでどちらかを指定
- 運用コストや効率性の観点からはLinux版ビルドを使用することが望ましい。
- フリートの初期化も早かった
ビルド時の注意点
- EC2インスタンスではGPUをサポートしていない
- UnityはゲームエンジンなのでGPUをしようとしてEC2サーバを起動しようとするとクラッシュする
- さけるために、サーバビルド時はheadlessモードにする。
buildOptions += BuildOptions,EnableHeadlessMode;
GameLiftへサーバをデプロイ
- AWS CLIでデプロイする。 例:
aws gamelift upload-build --operating-system AMAZON_LINUX --build-root C:\github\hogehoge\Build --name "HogeServer" --build-version "123"
- デプロイされるとビルド一覧に追加される。これをもとにフリートを作成する。
- フリートはビルドに紐づいたEC2インスタンス群のこと -フリートで選ぶ設定
- サーバプロセスの起動設定、引数とEC2インスタンスあたりの起動プロセス数を設定
- ポート開放の設定
- フリートが起動すると、プロセスなどのチェックが行われる。→問題なかったら起動!
GameLiftの開始
- 接続するにはAWS SDKのGameLift Service APIを使用する。
- CreateGameSession、CreatePlayerSession、SearchGameSessionsなど
- AWS SDKはC#版も提供されているため、Unityから直接APIを利用するっていうのもできなくはないが、相性やセキュリティ面からやめたほうが良い。
サーバエンジニアの手を煩わせないために
- AWS Lambdaを利用し関数を実装すればインフラを意識することなくバックエンドを実装できる。
- 言語の種類も多い。
- Unityが使えるエンジニアであればそのまま実装できちゃう。
- 補足:AWS Toolkit for VisualStudioを使うとVisualStudioで実装したLambda関数を直接AWSにもっていける
- そしてAWS API Gatewayと組み合わせることで、作成したLambda関数をREST APIとして使用できる
- クライアントからこのAPIをたたけばサーバのアドレスやポート番号を取得できる。後は接続するだけ
その他
Debug.LLogのサーバログ化
- GameLiftにはサーバログを保存する機能がある。
- Unityのログも出力できるようにした。
まとめ
- UnityとAWSを組み合わせることでオンラインマルチプレイゲームを比較的簡単に開発&運用することができる。
- 本格的なオンラインマルチプレイ開発の敷居が下がることで、今後より新しいゲーム性をもったタイトルが生まれてくるのではないか。
感想
ゲームサーバのインフラ環境を用意するのって意外に考慮する点が多いんだなと感じました。そういった課題をAWSのサービスの組み合わせてクリアしていて、AWSの幅広さに改めてすごいなーと思いました。このセッションではインフラの準備とサービスのデプロイが主な話でしたが、冒頭で紹介したスライドでは通信の実装周りが詳しく紹介されていますので、そちらもぜひご覧ください。とても面白かったですー!